//package com.mall.promo.mq;
//
//
//import com.alibaba.fastjson.JSON;
//import com.mall.order.dto.CreateSeckillOrderRequest;
//import com.mall.promo.cache.CacheManager;
//import com.mall.promo.dal.persistence.PromoItemMapper;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.rocketmq.client.exception.MQClientException;
//import org.apache.rocketmq.client.producer.LocalTransactionState;
//import org.apache.rocketmq.client.producer.TransactionListener;
//import org.apache.rocketmq.client.producer.TransactionMQProducer;
//import org.apache.rocketmq.client.producer.TransactionSendResult;
//import org.apache.rocketmq.common.message.Message;
//import org.apache.rocketmq.common.message.MessageExt;
//import org.redisson.Redisson;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//import java.nio.charset.Charset;
//import java.util.HashMap;
//import java.util.Map;
//
//@Component
//@Slf4j
//public class CreatePromoOrderProducer {
//
//    private TransactionMQProducer transactionMQProducer;  //该对象不是我们自己定义的，管理的；没有被@Service ，不会被spring容器管理；所以，我们应该：
//    //1. 定义init()方法；2.@PostConstruct注解---->使得spring容器可以调用init方法对TransactionMQProducer进行初始化
//
//    @Autowired
//    PromoItemMapper itemMapper;
//
//    @Autowired
//    CacheManager cacheManager;
//
//    @Autowired
//    RedissonClient redissonClient;
//
//    @PostConstruct
//    public void init() {
//        log.info("CreatePromoOrderProducer init start ...");
//        //1.创建事务的produer对象
//        transactionMQProducer = new TransactionMQProducer("create_promo_order_producer");
//        //2.设置发送地址
//        transactionMQProducer.setNamesrvAddr("127.0.0.1:9876");
//        //3.设置监听器：（1）执行本地方法；（2）检查本地事务执行结果
//        transactionMQProducer.setTransactionListener(new TransactionListener() {
//            /**
//             * 执行本地事务
//             * @param msg
//             * @param arg
//             * @return
//             */
//            @Override
//            public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
//                Map<String, Long> paramsMap = (Map<String, Long>) arg;
//                Long productId = paramsMap.get("productId");
//                Long psId = paramsMap.get("psId");
//                Integer effectiveRow = 0;
//
//                // 从Redis中获取一把锁
//                String lockKey = "create_promo_stock_" + productId + "_" + psId;
//                RLock lock = redissonClient.getLock(lockKey);
//
//                //分布式锁，同时只能被一个线程加锁成功，加锁失败的线程会阻塞等待
//                lock.lock();
//                try {
//                    effectiveRow = itemMapper.decreaseStock(productId, psId);
//                } finally {
//                    lock.unlock();
//                }
//
//                String localTransactionKey = "local_transaction_" + msg.getTransactionId();
//                if (effectiveRow < 1) {
//                    //  没有库存了
//
//                    // 向redis中放入库存售罄的标志
//                    String notEnoughKey = "promo_product_not_engough_" + productId + "_" + psId;
//                    cacheManager.setCache(notEnoughKey, "none", 1);
//
//                    cacheManager.setCache(localTransactionKey, "rollback", 1);
//                    return LocalTransactionState.ROLLBACK_MESSAGE;
//                }
//
//                // 有库存，可以下单
//                cacheManager.setCache(localTransactionKey, "commit", 1);
//                return LocalTransactionState.COMMIT_MESSAGE;
//            }
//
//            /**
//             * 检查本地事务执行结果
//             * @param msg
//             * @return
//             */
//            @Override
//            public LocalTransactionState checkLocalTransaction(MessageExt msg) {
//                String localTransactionKey = "local_transaction_" + msg.getTransactionId();
//                String transactionResult = cacheManager.checkCache(localTransactionKey);
//
//                if (transactionResult != null && "commit".equals(transactionResult.trim())) {
//                    // 有库存，本地事务执行成功
//                    return LocalTransactionState.COMMIT_MESSAGE;
//                }
//
//                if (transactionResult != null && "rollback".equals(transactionResult.trim())) {
//                    // 没有库存，订单服务不需要消费消息去下单
//                    return LocalTransactionState.ROLLBACK_MESSAGE;
//                }
//
//                return LocalTransactionState.UNKNOW;
//            }
//        });
//        //4.启动
//        try {
//            transactionMQProducer.start();
//            log.info("CreatePromoOrderProducer init end ...");
//            return;
//        } catch (MQClientException e) {
//            e.printStackTrace();
//        }
//        log.info("CreatePromoOrderProducer init failed ...");
//    }
//
//
//    /**
//     * 提供给PromoServiceImpl进行调用，发送事务消息的方法
//     * @param request
//     * @param productId
//     * @param psId
//     * @return
//     */
//    public boolean sendPromoTransactionMessage(CreateSeckillOrderRequest request, Long productId, Long psId) {
//        // 将request对象转化为json字符串
//        String requestStr = JSON.toJSONString(request);
//        // 准备本地事务执行所需要的参数
//        HashMap<String, Long> parmsMap = new HashMap<>();
//        parmsMap.put("productId", productId);
//        parmsMap.put("psId", psId);
//        // 1. 准备待发送的消息
//        Message message = new Message();
//        message.setTopic("creat_promo_order");
//        message.setBody(requestStr.getBytes(Charset.forName("utf-8")));
//        TransactionSendResult sendResult = null;
//        try {
//
//            sendResult = transactionMQProducer.sendMessageInTransaction(message, parmsMap);
//
//        } catch (MQClientException e) {
//            e.printStackTrace();
//        }
//
//        if (sendResult != null && LocalTransactionState.COMMIT_MESSAGE.equals(sendResult.getLocalTransactionState())) {
//            return true;
//        }
//
//        return false;
//    }
//}
